package org.jeecg.modules.dock.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dtflys.forest.http.ForestResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.dock.client.MdsRequestClient;
import org.jeecg.modules.dock.config.JsonUtils;
import org.jeecg.modules.dock.constant.SystemConstants;
import org.jeecg.modules.dock.entity.DockDataSendRecord;
import org.jeecg.modules.dock.entity.DockTaskRecordMap;
import org.jeecg.modules.dock.entity.mds.MdsBaseResponseVO;
import org.jeecg.modules.dock.entity.mds.request.*;
import org.jeecg.modules.dock.enums.DockDataStatus;
import org.jeecg.modules.dock.service.IDockDataSendRecordService;
import org.jeecg.modules.dock.service.IDockTaskRecordMapService;
import org.jeecg.modules.dock.service.MdsDockingRepeaterService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * mds业务对接服务实现类
 *
 * @author zhoutong
 */
@Service
@AllArgsConstructor
@Slf4j
public class MdsDockingRepeaterServiceImpl implements MdsDockingRepeaterService {

    private final MdsRequestClient mdsRequestClient;

    private final IDockDataSendRecordService dockDataSendRecordService;

    private final IDockTaskRecordMapService dockTaskRecordMapService;

    private static final List<Integer> MDS_LOCATION_ID = Arrays.asList(1, 2, 3, 4);

    private DockDataSendRecord saveRecord(Object data, MdsBaseResponseVO mdsBaseResponseVO) {
        DockDataSendRecord sendRecord = new DockDataSendRecord();
        sendRecord.setSource(SystemConstants.WMS);
        sendRecord.setTarget(SystemConstants.MDS);
//        sendRecord.setBusinessCode(SapInterfaceTypeEnum.SALE_OUTBOUND_POST.getCode());
        sendRecord.setUuid(IdUtil.fastSimpleUUID());
        sendRecord.setSendTime(new Date());
        sendRecord.setData(JSONObject.toJSONString(data));
        sendRecord.setResultCode(mdsBaseResponseVO.getTarget());
        sendRecord.setStatus(DockDataStatus.SUCCESS);
        sendRecord.setResultData(ObjectUtil.isNotEmpty(mdsBaseResponseVO)
                ? JsonUtils.toJson(mdsBaseResponseVO) : "");
        dockDataSendRecordService.save(sendRecord);
        return sendRecord;
    }

    private MdsBaseResponseVO returnVO(ForestResponse<MdsBaseResponseVO> response) {
        if (response == null) {
            return MdsBaseResponseVO.error("请求出错");
        }
        MdsBaseResponseVO result = response.getResult();
        log.info("wms请求mds状态{},路径：{}， 返回数据：{}", response.getStatusCode(),
                response.getRequest().path(), result);
        if (response.isSuccess() && result != null && MdsBaseResponseVO.SUCCESS.equals(result.getTarget())) {
            return MdsBaseResponseVO.ok();
        }
        return result == null ? MdsBaseResponseVO.error("请求出错") : result;
    }

    @Override
    public MdsBaseResponseVO mdsTransverseShearingIsCalledMaterial(MDSTransverseShearingIsCalledMaterialRequestVO vo) {
        log.info("mds-横剪叫料请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsTransverseShearingIsCalledMaterial(vo);
            log.info("mds-横剪叫料请求成功！");
        } catch (Exception e) {
            log.error("mds-横剪叫料请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsCrossShearingToWithdrawMaterial(MDSCrossShearingToWithdrawMaterialRequestVO vo) {
        log.info("mds-横剪退料请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsCrossShearingToWithdrawMaterial(vo);
            log.info("mds-横剪退料请求成功！");
        } catch (Exception e) {
            log.error("mds-横剪退料请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsTransverseShearIsCalledMaterialPlate(MDSTransverseShearIsCalledMaterialPlateRequestVO vo) {
        log.info("mds-横剪叫料板请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsTransverseShearIsCalledMaterialPlate(vo);
            log.info("mds-横剪叫料板请求成功！");
        } catch (Exception e) {
            log.error("mds-横剪叫料板请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsTheTransverseShearIsCalledAScrapBin(MDSTheTransverseShearIsCalledAScrapBinRequestVO vo) {
        log.info("mds-横剪叫废料箱请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsTheTransverseShearIsCalledAScrapBin(vo);
            log.info("mds-横剪叫废料箱请求成功！");
        } catch (Exception e) {
            log.error("mds-横剪叫废料箱请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsCrossCutTheScrapBin(MDSCrossCutTheScrapBinRequestVO vo) {
        log.info("mds-横剪退废料箱请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsCrossCutTheScrapBin(vo);
            log.info("mds-横剪退废料箱请求成功！");
        } catch (Exception e) {
            log.error("mds-横剪退废料箱请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsCrossCutIntoStorage(MDSCrossCutIntoStorageRequestVO vo) {
        log.info("mds-横剪入库请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsCrossCutIntoStorage(vo);
            log.info("mds-横剪入库请求成功！");
        } catch (Exception e) {
            log.error("mds-横剪入库请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsLaminationIsCalledMaterial(MDSLaminationIsCalledMaterialRequestVO vo) {
        log.info("mds-叠片叫料请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsLaminationIsCalledMaterial(vo);
            log.info("mds-叠片叫料请求成功！");
        } catch (Exception e) {
            log.error("mds-叠片叫料请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsLaminationAndRefeeding(MDSLaminationAndRefeedingRequestVO vo) {
        log.info("mds-叠片退料请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsLaminationAndRefeeding(vo);
            log.info("mds-叠片退料请求成功！");
        } catch (Exception e) {
            log.error("mds-叠片退料请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO mdsLaminatedRefeedingPlate(MDSLaminatedRefeedingPlateRequestVO vo) {
        log.info("mds-叠片退料板请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.mdsLaminatedRefeedingPlate(vo);
            log.info("mds-叠片退料板请求成功！");
        } catch (Exception e) {
            log.error("mds-叠片退料板请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO materialTransferAndWarehousing(MaterialTransferAndWarehousingRequestVO vo) {
        log.info("mds-条料调拨入库请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.materialTransferAndWarehousing(vo);
            log.info("mds-条料调拨入库请求成功！");
        } catch (Exception e) {
            log.error("mds-条料调拨入库请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO malledMaterialRack(MalledMaterialRackRequestVO vo) {
        log.info("mds-条料库叫料架请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.malledMaterialRack(vo);
            log.info("mds-条料库叫料架请求成功！");
        } catch (Exception e) {
            log.error("mds-条料库叫料架请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO materialTransferAndOutbound(MaterialTransferAndOutboundRequestVO vo) {
        log.info("mds-条料调拨出库请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.materialTransferAndOutbound(vo);
            log.info("mds-条料调拨出库请求成功！");
        } catch (Exception e) {
            log.error("mds-条料调拨出库请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO forceComplete(ForceCompleteRequestVO vo) {
        log.info("mds-强制完成请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            DockTaskRecordMap dockTaskRecordMap = dockTaskRecordMapService.getOne(new LambdaQueryWrapper<DockTaskRecordMap>().eq(DockTaskRecordMap::getMesTaskCode, vo.getTaskCode()));
            if (ObjectUtil.isNotEmpty(dockTaskRecordMap)) {
                vo.setSite(dockTaskRecordMap.getSite());
            }
            response = mdsRequestClient.forceComplete(vo);
            log.info("mds-强制完成请求成功！");
        } catch (Exception e) {
            log.error("mds-强制完成请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO delivery(MDSDeliveryRequestVO vo) {
        log.info("mds-配送请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.delivery(vo);
            log.info("mds-配送请求成功！");
        } catch (Exception e) {
            log.error("mds-配送请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public MdsBaseResponseVO emptyMaterialRack(EmptyMaterialRackRequestVO vo) {
        log.info("mds-退空料架请求开始：【{}】", vo);
        ForestResponse response = null;
        MdsBaseResponseVO mdsBaseResponseVO = null;
        try {
            response = mdsRequestClient.emptyMaterialRack(vo);
            log.info("mds-退空料架请求成功！");
        } catch (Exception e) {
            log.error("mds-退空料架请求失败", e.getMessage(), e);
        } finally {
            mdsBaseResponseVO = returnVO(response);
            saveRecord(vo, mdsBaseResponseVO);
        }
        return mdsBaseResponseVO;
    }

    @Override
    public List<MdsRepertoryVO> repertory() {

        long begin = System.currentTimeMillis();
        List<MdsRepertoryVO> result = new ArrayList<>();
        List<MdsRepertoryVO> totalResult = new ArrayList<>();
        for (Integer id : MDS_LOCATION_ID) {
            ForestResponse<List<MdsRepertoryVO>> repertory = mdsRequestClient.repertory(id);
            List<MdsRepertoryVO> res = repertory.getResult();
            log.info("wms请求mds状态{},路径：{}， 返回数据数：{}", repertory.getStatusCode(),
                    repertory.getRequest().path(), res.size());
            if (repertory.isSuccess()) {
                totalResult.addAll(res);
            }
        }
        for (MdsRepertoryVO vo : totalResult) {
            if (CollectionUtil.isNotEmpty(vo.getDetail())) {
                for (MdsRepertoryVO.Detail detail : vo.getDetail()) {
                    MdsRepertoryVO vo1 = new MdsRepertoryVO();
                    BeanUtils.copyProperties(vo, vo1);
                    vo1.setBatchId(detail.getBatchId());
                    vo1.setModelName(detail.getModelName());
                    vo1.setDirection(detail.getDirection());
                    vo1.setTableCode(detail.getTableCode());
                    result.add(vo1);
                }
            } else {
                result.add(vo);
            }
        }
        log.info("查询mds即时库存耗时：{} ms", System.currentTimeMillis() - begin);
        return result;
    }

    private List<MdsRepertoryVO> select(List<MdsRepertoryVO> totalResult) {
        Integer sAreaId = null, sLocation = null;
        String batchId = null, modelName = null;
        Set<MdsRepertoryVO> result = new HashSet<>();
        Set<MdsRepertoryVO> resultAreaId = new HashSet<>();
        Set<MdsRepertoryVO> resultLocation = new HashSet<>();
        Set<MdsRepertoryVO> resultBatchId = new HashSet<>();
        Set<MdsRepertoryVO> resultModelName = new HashSet<>();
        boolean flag = false;
        if (sAreaId != null || sLocation != null || StringUtils.isNotBlank(batchId)
                || StringUtils.isNotBlank(modelName)) {
            flag = true;
            for (MdsRepertoryVO repertoryVO : totalResult) {
                if (sAreaId != null && sAreaId.equals(repertoryVO.getAreaId())) {
                    resultAreaId.add(repertoryVO);
                }
                if (sLocation != null && sLocation.equals(repertoryVO.getLocationId())) {
                    resultLocation.add(repertoryVO);
                }
                if (StringUtils.isNotBlank(batchId) && batchId.equals(repertoryVO.getBatchId())) {
                    resultBatchId.add(repertoryVO);
                }
                if (StringUtils.isNotBlank(modelName) && modelName.equals(repertoryVO.getModelName())) {
                    resultModelName.add(repertoryVO);
                }
            }
        }

        if (sAreaId != null) {
            result.addAll(resultAreaId);
        } else if (sLocation != null) {
            result.addAll(resultLocation);
        } else if (StringUtils.isNotBlank(batchId)) {
            result.addAll(resultBatchId);
        } else if (StringUtils.isNotBlank(modelName)) {
            result.addAll(resultModelName);
        }
        if (flag) {
            if (sAreaId != null) {
                result.retainAll(resultAreaId);
            }
            if (sLocation != null) {
                result.retainAll(resultLocation);
            }
            if (StringUtils.isNotBlank(batchId)) {
                result.retainAll(resultBatchId);
            }
            if (StringUtils.isNotBlank(modelName)) {
                result.retainAll(resultModelName);
            }
            return new ArrayList<>(result);
        }

        return totalResult;

    }


}
